package service

import (
	"context"
	"encoding/json"
	"fmt"
	"github.com/pkg/errors"
	"gorm.io/gorm"
	"mall/api/mall"
	"mall/api/prod"
	"mall/internal/constant"
	"mall/internal/generator"
	"mall/internal/model"
	"mall/pkg/ecode"
	"mall/pkg/orm"
	"mall/pkg/util"
	"strconv"
	"strings"
	"time"
)

// 查看购物车
func (s *Service) GetCustomerCart(ctx context.Context, req *mall.CustomerRequest) (
	resp *mall.GetCustomerCartResp, err error) {
	var (
		cartProds  []*model.Cart
		shelfProds []*model.ShelfProd
		shelfSkus  []*model.ShelfSku
	)
	if cartProds, err = s.dao.FindCartProds(ctx, req.Token.MemberId); err != nil {
		return
	}
	resp = &mall.GetCustomerCartResp{CartProds: make([]*mall.CartProd, len(cartProds))}
	prodIdMap := make(util.Int64BoolMap)
	storeIdMap := make(util.Int32BoolMap)
	skuIdMap := make(util.Int64BoolMap)
	for _, cartProd := range cartProds {
		prodIdMap[cartProd.ProdId] = true
		storeIdMap[cartProd.StoreId] = true
		skuIdMap[cartProd.SkuId] = true
	}
	if len(cartProds) != 0 {
		if shelfProds, err = s.dao.FindOnShelfProdsByProdIdsAndStoreIds(
			ctx, req.Token.SgId, storeIdMap.GetKeys(), prodIdMap.GetKeys()); err != nil {
			return
		}
		if shelfSkus, err = s.dao.FindOnShelfSkusBySkuIdsAndStoreIds(
			ctx, req.Token.SgId, storeIdMap.GetKeys(), skuIdMap.GetKeys()); err != nil {
			return
		}
		prodKeyMap := make(map[string]*model.ShelfProd)
		skuKeyMap := make(map[string]*model.ShelfSku)
		for _, shelfProd := range shelfProds {
			prodKeyMap[fmt.Sprintf("%d-%d", shelfProd.ProdId, shelfProd.PStoreId)] = shelfProd
		}
		for _, shelfSku := range shelfSkus {
			skuKeyMap[fmt.Sprintf("%d-%d", shelfSku.SkuId, shelfSku.PStoreId)] = shelfSku
		}
		for i, cartProd := range cartProds {
			prodKey := fmt.Sprintf("%d-%d", cartProd.ProdId, cartProd.StoreId)
			skuKey := fmt.Sprintf("%d-%d", cartProd.SkuId, cartProd.StoreId)
			shelfProd, prodOk := prodKeyMap[prodKey]
			shelfSku, skuOk := skuKeyMap[skuKey]
			cartRemark := &model.CartRemark{}
			if err = json.Unmarshal(cartProd.Remark, cartRemark); err != nil {
				err = ecode.WithStack(err)
				return
			}
			if prodOk && skuOk {
				// 商品仍在货架上，除门店名称外展示商品信息
				resp.CartProds[i] = &mall.CartProd{
					ProdId:    cartProd.ProdId,
					SkuId:     cartProd.SkuId,
					ProdName:  getCustomName(shelfProd),
					SkuName:   strings.Join(shelfSku.SyncItems, "/"),
					StoreId:   cartProd.StoreId,
					Price:     getCustomPrice(shelfSku),
					Quantity:  cartProd.Quantity,
					Unit:      shelfProd.SyncUnit,
					Pic:       shelfProd.SyncPic,
					Status:    true,
					Weight:    shelfSku.SyncWeight,
					StoreName: cartRemark.StoreName,
					Nature:    prod.Nature(cartRemark.Nature),
				}
			} else {
				// 展示快照信息
				resp.CartProds[i] = &mall.CartProd{
					ProdId:    cartProd.ProdId,
					SkuId:     cartProd.SkuId,
					ProdName:  cartRemark.ProdName,
					SkuName:   cartRemark.SkuName,
					StoreId:   cartProd.StoreId,
					Price:     cartRemark.Price,
					Quantity:  cartProd.Quantity,
					Unit:      cartRemark.Unit,
					Pic:       cartRemark.Pic,
					Status:    false,
					Weight:    cartRemark.Weight,
					StoreName: cartRemark.StoreName,
					Nature:    prod.Nature(cartRemark.Nature),
				}
			}
		}
	}
	return
}

// 购物车变更
func (s *Service) ModifyCart(ctx context.Context, req *mall.ModifyCartRequest) (
	resp *mall.DefaultResp, err error) {
	if req.Quantity != 0 {
		var (
			shelfProd *model.ShelfProd
			shelfSku  *model.ShelfSku
			cartProd  *model.Cart
		)
		if shelfProd, err = s.dao.GetShelfProd(
			ctx, req.ProdId, req.Token.SgId, req.StoreId); err != nil {
			if errors.Cause(err) == gorm.ErrRecordNotFound {
				err = ecode.AppendMessage(constant.ErrForbiddenAction,
					"所选商品已下架，无法加入购物车或更改数量")
			}
			return
		}
		if shelfSku, err = s.dao.GetShelfSku(ctx, req.SkuId, req.Token.SgId, req.StoreId); err != nil {
			if errors.Cause(err) == gorm.ErrRecordNotFound {
				err = ecode.AppendMessage(constant.ErrForbiddenAction,
					"所选商品已下架，无法加入购物车或更改数量")
			}
			return
		}
		var remark json.RawMessage
		if remark, err = json.Marshal(&model.CartRemark{
			ProdName:  getCustomName(shelfProd),
			SkuName:   strings.Join(shelfSku.SyncItems, "/"),
			Price:     getCustomPrice(shelfSku),
			Unit:      shelfProd.SyncUnit,
			Pic:       shelfProd.SyncPic,
			Weight:    shelfSku.SyncWeight,
			StoreName: req.StoreName,
			Nature:    shelfProd.SyncNature,
		}); err != nil {
			err = ecode.WithStack(err)
			return
		}
		if cartProd, err = s.dao.GetCartProd(ctx, req.Token.MemberId, req.SkuId); err != nil {
			if errors.Cause(err) == gorm.ErrRecordNotFound {
				// 新建
				if err = s.dao.Create(ctx, &model.Cart{
					MemberId: req.Token.MemberId,
					SkuId:    req.SkuId,
					StoreId:  req.StoreId,
					ProdId:   req.ProdId,
					Quantity: req.Quantity,
					Remark:   orm.JSON(remark),
				}); err != nil {
					return
				}
			} else {
				return
			}
		} else {
			// 更新
			cartProd.ProdId = req.ProdId
			cartProd.StoreId = req.StoreId
			cartProd.Quantity = req.Quantity
			cartProd.Remark = orm.JSON(remark)
			if err = s.dao.Save(ctx, cartProd); err != nil {
				return
			}
		}
	} else {
		// 删除
		if err = s.dao.DeleteCartBySkuIds(ctx, req.Token.MemberId, []uint64{req.SkuId}); err != nil {
			return
		}
	}
	resp = &mall.DefaultResp{Status: true}
	return
}

// 批量删除购物车
func (s *Service) DeleteCart(ctx context.Context, req *mall.DeleteCartRequest) (
	resp *mall.DefaultResp, err error) {
	// 删除
	if err = s.dao.DeleteCartBySkuIds(ctx, req.Token.MemberId, req.SkuIds); err != nil {
		return
	}
	resp = &mall.DefaultResp{Status: true}
	return
}

// 生成购物车结算页唯一ID接口
func (s *Service) GenCustomerRequestId(ctx context.Context, req *mall.CustomerRequest) (
	resp *mall.GenCustomerRequestIdResp, err error) {
	var requestId string
	if requestId, err = generator.GenerateOrderNumber(
		time.Now(), int(mall.OrderType_ORDER_TYPE_BIZ), strconv.Itoa(int(req.Token.MemberId))); err != nil {
		return
	}
	resp = &mall.GenCustomerRequestIdResp{
		RequestId: requestId,
	}
	return
}

// 经销商模式查询发货仓
func (s *Service) GetDeliverStore(ctx context.Context, req *mall.CustomerStoreRequest) (
	resp *mall.DeliverStoreResp, err error) {
	resp = &mall.DeliverStoreResp{}
	if req.Id != 0 {
		if _, err = s.dao.GetConfigByStoreId(ctx, req.Token.SgId, req.Id); err != nil {
			if errors.Cause(err) == gorm.ErrRecordNotFound {
				err = nil
				// 代发模式
			}
			return
		} else {
			// 自行发货
			resp.Id = req.Id
		}
	}
	return
}

// 获取商城业务的小程序模板消息
func (s *Service) GetMallWechatTemplates(ctx context.Context, req *mall.CustomerRequest) (
	resp *mall.GetMallWechatTemplatesResp, err error) {
	resp = &mall.GetMallWechatTemplatesResp{}
	if resp.TemplateIds, err = s.downstream.GetWechatTemplates(ctx, req.Token.AppId); err != nil {
		return
	}
	return
}
